package cn.virens.dd.simple;

import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.atomic.AtomicBoolean;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReUtil;
import cn.virens.common.utils.common.CalendarUtil;
import cn.virens.dd.Strategy;
import cn.virens.dd.StrategyTask;
import cn.virens.dd.StrategyValue;
import cn.virens.dd.stack.StrategyTaskStack;

public abstract class AbstractStrategy<T extends StrategyValue> implements Strategy {
	private final StrategyTaskStack taskStack = new StrategyTaskStack();
	private final AtomicBoolean flag = new AtomicBoolean(true);

	private volatile Date changeTime;

	@Override
	@SuppressWarnings("unchecked")
	public boolean filter(StrategyValue value) {
		return changeFlag(filter0((T) value));
	}

	public boolean getFlag() {
		return flag.get();
	}

	public Date getChangeTime() {
		return changeTime;
	}

	@Override
	public Collection<StrategyTask> task() {
		return this.taskStack.values();
	}

	@Override
	public boolean putTask(String uid, StrategyTask task) {
		return this.taskStack.put(uid, task) == null;
	}

	protected abstract boolean filter0(T value);

	/** 判断执行标识位是否发生变化(没变肯定是false,变了不一定是true) */
	protected boolean changeFlag(boolean answer) {
		if (flag.compareAndSet(!answer, answer)) {
			this.changeTime = DateUtil.date();
		} else {
			return false;
		}

		// 返回变化后的状态值
		return flag.get();
	}

	/** 判断是不是标准的时间格式 */
	protected static boolean isTime(String time) {
		return ReUtil.isMatch("\\d{1,2}:\\d{1,2}", time);
	}

	/** 获取时间戳中的当日分钟数 */
	protected static int minutes(Date time) {
		Calendar calendar = CalendarUtil.clone(time);
		int h = calendar.get(Calendar.HOUR_OF_DAY);
		int m = calendar.get(Calendar.MINUTE);

		return h * 60 + m;
	}

	/** 比较time1是否在time2之前(不比较日期) */
	protected static boolean before(Date time1, Date time2) {
		int m1 = time1 != null ? minutes(time1) : 0;
		int m2 = time1 != null ? minutes(time2) : 0;

		// 如果m1>23:50 & m2<00:10 就返回 true
		if (m1 > (23 * 60 + 50) && m2 < 10) {
			return m1 >= m2;
		} else {
			return m1 <= m2;
		}
	}

	/** 比较输入时间time是否处于time1与time2之间(不比较日期) */
	protected static boolean between(Date time1, Date time2, Date time) {
		int m1 = time1 != null ? minutes(time1) : 0;
		int m2 = time2 != null ? minutes(time2) : 0;
		int m = time != null ? minutes(time) : 0;

		// 补偿跨日期的时间值
		if (m1 > m2) m2 += (24 * 60);

		// 时间值比较time
		return m1 <= m && m < m2;
	}

	/** 转换HH:mm格式的字符串为时间对象,如果不符合条件将返回null */
	protected static DateTime parseTimeByHM(String time) {
		return isTime(time) ? DateUtil.parse(time, "HH:mm") : null;
	}
}
